Each file has a header, an array of MapInfoBlocks, and strings for the image
file names and file types.
Some also have StringInfoBlocks, function unknown.
typedef struct tagMapInfoBlock
{
DWORD dwMapTypeOffset;
// The start of a string for the type of image map.
BYTE Unk0[4];
// Unk[1] looks like a type enumeration where "colorMap" = 2.
DWORD dwMapNameOffset; // The start
of a string for the image file name.
}MapInfoBlock;
typedef struct tagStringInfoBlock
{
DWORD dwMapTypeOffset; // The start of an info string.
float Unk1[4];
// Four floats, function unknown.
}StringInfoBlock;
Note1: All offsets are from the beginning of the file.
Note2: All strings are C style, zero terminated.
typedef struct tagHeader
{
DWORD dwMaterialNameOffset;
// Not very useful since it always seems to be same as material filename.
DWORD dwColorMapFilenameOffset;
// A shortcut to the most important map, the mesh's skin.
BYTE Unk2[0x2c];
WORD nNumMapInfoBlocks;
// See above.
WORD nNumMapInfoStrings;
// Not sure of their function.
DWORD dwMaterialTypeOffset;
DWORD dwMapInfoBlockOffset;
// Always 0x44; Offset to the first MapInfoBlock
DWORD Unk3;
DWORD dwStringInfoBlockOffset;
// Offset to the first StringInfoBlock;
}MaterialHeader;
CString CXmodelCoD2::MaterialToMap(CString &sMaterialFileName, CString sMapType)
{
// Valid MapTypes are:
// "colorMap",
// "detailMap",'
// "normalMap",
// "specularMap"
// These are the names in the material file.
//
// Returns the requested
filename or "" if not found.
CString sRet("");
CFile file;
char buffer[255];
if(file.Open(sMaterialFileName,
CFile::modeRead))
{
MaterialHeader header;
file.Read(&header,
sizeof(MaterialHeader));
MapInfoBlock* pBlocks = new MapInfoBlock[header.wNumMapInfoBlocks];
// Move to first
MapInfoBlock and read them all in.
file.Seek(header.dwInfoBlockOffset, CFile::begin);
file.Read(pBlocks, sizeof(MapInfoBlock)):
// If interested
in them, the file pointer is now pointing to the InfoStringBlocks
for(WORD
i = 0; i < header.wNumMapInfoBlocks; i++)
{
file.Seek(pBlocks[i].dwMapTypeOffset,
CFile::begin);
file.Read(buffer,
255); // Just grab a bunch;
CString sTemp(buffer);
if(sTemp == sMapType)
{
file.Seek(pBlocks[i].dwMapNameOffset, CFile::begin);
file.Read(buffer, 255);
sRet = buffer;
sRet += ".iwi";
break;
}
}
delete[] pBlocks;
}
file.Close();
return sRet;
}
Note 3: This code was typed from memory. If it compiles, I wrote it. If not, then Anonymous wrote it.